<template>
  <div>
    <!--全局组件:商品分类全局组件-->
    <Category :scene="scene"></Category>
    <!--平台属性管理模块底部的结构-->
    <el-card shadow="always" style="margin: 10px 0px">
      <div v-show="scene == 0">
        <el-button :disabled="categoryStore.c3Id ? false : true" type="primary" size="default" :icon="Plus"
          @click="changeScene">添加平台属性</el-button>
        <!--展示平台属性的表格的地方-->
        <el-table border stripe style="margin: 10px 0px" :data="attrArr">
          <el-table-column label="序号" width="80px" type="index" align="center"></el-table-column>
          <el-table-column label="属性名称" width="120px" prop="attrName"></el-table-column>
          <el-table-column label="属性值名称">
            <template #="{ row, $index }">
              <el-tag style="margin: 0px 5px" :type="item.id % 2 == 0 ? 'success' : 'warning'"
                v-for="(item, index) in row.attrValueList" :key="index">{{ item.valueName }}</el-tag>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="120px">
            <!-- row:代表的是一个已有的平台属性 -->
            <template #="{ row, $index }">
              <el-button type="warning" size="small" :icon="Edit" @click="updateAttr(row)"></el-button>
              <el-popconfirm :title="`你确定要删除${row.attrName}?`" width="200" @confirm="removeAttr(row.id)">
                <template #reference>
                  <el-button type="danger" size="small" :icon="Delete"></el-button>
                </template>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <div v-show="scene == 1">
        <!--添加属性|修改属性的静态-->
        <el-form :inline="true" :model="attrParams" :rules="rules" ref="form">
          <el-form-item label="属性名字" prop="attrName">
            <el-input placeholder="请你输入属性的名称" v-model="attrParams.attrName"></el-input>
          </el-form-item>
        </el-form>
        <el-button type="primary" size="default" :icon="Plus" @click="addAttrValue"
          :disabled="attrParams.attrName ? false : true">添加属性值</el-button>
        <el-button type="primary" size="default" @click="cancel">取消</el-button>
        <!-- 展示属性值的地方 -->
        <el-table border stripe style="margin: 10px 0px" :data="attrParams.attrValueList">
          <el-table-column label="序号" width="80" type="index" align="center"></el-table-column>
          <el-table-column label="属性值">
            <!--row:代表的是属性值对象--->
            <template #="{ row, $index }">
              <el-input :ref="(el) => (inputArr[$index] = el)" v-if="row.show" @blur="toLook(row, $index)" size="small"
                v-model="row.valueName" placeholder="请你输入属性值"></el-input>
              <div v-else @click="toEdit(row, $index)">{{ row.valueName }}</div>
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <template #="{ row, $index }">
              <el-popconfirm :title="`你确定要删除${row.valueName}?`" width="200px" @confirm="handler($index)">
                <template #reference>
                  <el-button size="small" :icon="Delete" type="danger"></el-button>
                </template>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
        <el-button :disabled="attrParams.attrValueList.length == 0 ? true : false" type="primary" size="default"
          @click="save">保存<el-icon class="el-icon--right">
            <WalletFilled />
          </el-icon></el-button>
        <el-button type="primary" size="default" @click="cancel">取消</el-button>
      </div>
    </el-card>
  </div>
</template>

<script setup lang="ts">
import cloneDeep from "lodash/cloneDeep";
import { Plus, Edit, Delete, WalletFilled } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
//引入watch
import { watch, ref, nextTick, onUnmounted } from "vue";
//引入请求函数
import {
  reqAttrList,
  reqAddOrUpdateAttr,
  reqRemoveAttr,
} from "../../../api/product/attr/index";
//引入商品分类小仓库
import { default as useCategoryStore } from "../../../stores/category";
import type {
  responseAttrData,
  attr,
  attrValue,
} from "../../../api/product/attr/model/index";
//获取小仓库
let categoryStore = useCategoryStore();
//响应式数据:控制场景切换
let scene = ref<number>(0);
//响应式数据存储平台属性与属性值
let attrArr = ref<responseAttrData>([]);
let form = ref<any>(null);

//定义响应式数据,将来用于存储表单元素VC
let inputArr: any = ref([]);
//新增一个属性的需要携带的参数
let attrParams = ref<attr>({
  attrName: "", //属性的名字
  attrValueList: [],
  categoryId: "", //某一个三级分类ID
  categoryLevel: 3, //给某一个三级分类添加属性
});
//watch写法:四种写法 ref对象|代理对象|箭头函数|数组
//watch与watchEffect区别?
//watch惰性监听,数据需要发生变化，才能监听到  watchEffect立马监听一次
//watch能确定监听的事件源，watchEffect不能确定监听的事件源
//watch可以知道监听事件源新旧的数值，watchEffect监听不到数据新旧的变化
watch(
  () => categoryStore.c3Id,
  () => {
    attrArr.value = [];
    //约束三级分类的ID不能为空
    if (categoryStore.c3Id == "") return;
    //监听到三级分类的变化,发请求获取这个三级分类下的平台属性与属性值的数据
    getAttrList();
  }
);
//请求平台属性与属性值的方法
const getAttrList = async () => {
  //准备参数:一级、二级、三级分类的ID
  let c1Id = categoryStore.c1Id,
    c2Id = categoryStore.c2Id,
    c3Id = categoryStore.c3Id;
  let result: responseAttrData = await reqAttrList(c1Id, c2Id, c3Id);
  //存储平台属性与属性值的数据
  attrArr.value = result;
};

//添加属性的按钮的回调(点击事件)
const changeScene = () => {
  //切换场景为1
  scene.value = 1;
  //第一种写法:每一个属性一个一个清空
  // attrParams.value.attrName = '';
  // attrParams.value.attrValueList=[];
  // attrParams.value.categoryId = '';

  //合并对象:Objet.assign
  Object.assign(attrParams.value, {
    attrName: "19933462711", //属性的名字
    attrValueList: [],
    categoryId: categoryStore.c3Id, //某一个三级分类ID
    categoryLevel: 3, //给某一个三级分类添加属性
  });
};

//取消按钮的回调
const cancel = () => {
  scene.value = 0;
};

//添加属性值按钮回调
const addAttrValue = () => {
  //点击添加属性值按钮:收集的属性值数组添加一个对象[收集属性值数据]
  //代表平台属性值的数组添加一个新增的属性值
  attrParams.value.attrValueList.push({
    valueName: "",
    show: true, //控制每一个属性值的编辑模式与查看模式切换
  });

  //获取表单元素:自动聚焦[最后的表单元素聚焦]
  nextTick(() => {
    inputArr.value[inputArr.value.length - 1].focus();
  });
};

//保存按钮
const save = async () => {
  //校验全部表单相
  await form.value.validate();
  //新增一个属性|更新一个已有属性
  try {
    //添加属性|修改成功
    await reqAddOrUpdateAttr(attrParams.value);
    //顶部文字的提示
    ElMessage({
      message: attrParams.value.id ? "修改成功" : "添加成功",
      type: "success",
    });
    //切换场景为零
    scene.value = 0;
    //再次获取更新后属性与属性值
    getAttrList();
  } catch (error) {
    ElMessage({
      message: attrParams.value.id ? "修改失败" : "添加失败",
      type: "error",
    });
  }
};

//表单元素blur事件->查看模式
//row:即为一个属性值对象
const toLook = (row: attrValue) => {
  //非法情况的判断:失去焦点的时候非法判断
  //非法情况1:属性值不能为空
  if (row.valueName.trim() == "") {
    //属性值为空后面语句就不能在执行,不能变为div
    ElMessage({
      message: "属性值不能为空",
      type: "warning",
    });
    //属性值是空的，也从数组里面干掉
    attrParams.value.attrValueList.splice(
      attrParams.value.attrValueList.indexOf(row),
      1
    );
    return;
  }

  //非法情况2:属性值的名字不能重复
  //失却焦点的属性值判断在属性值数组当中是否出现过
  let repeat = attrParams.value.attrValueList.find((item) => {
    if (row != item) {
      //把数组当中自己先扣除去,再去判断有没有重复的
      return item.valueName === row.valueName;
    }
  });
  //代表属性值有重复的
  if (repeat) {
    ElMessage({
      type: "warning",
      message: "属性值重复了",
    });
    //把重复元素干掉
    attrParams.value.attrValueList.splice(
      attrParams.value.attrValueList.indexOf(row),
      1
    );
    return;
  }

  //变为查看模式
  row.show = false;
};

//div的点击事件回调,变为编辑模式显示input
const toEdit = (row: attrValue, index: number) => {
  row.show = true;
  //获取表单元素的VC聚焦
  nextTick(() => {
    //表单元素聚焦
    inputArr.value[index].focus();
  });
};

const validatorAttrName = (rule: any, value: string, callBack: any) => {
  if (/^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$/.test(value)) {
    callBack();
  } else {
    callBack(new Error("属性名称务必是手机号码"));
  }
};

//表单验证规则对象
const rules: any = {
  //required:务必校验这个字段 ->表单相前面加上星星
  //trigger:blur|change
  attrName: [
    { required: true, trigger: "change", validator: validatorAttrName },
  ],
};
//气泡确认框确定按钮的回调
const handler = (index: number) => {
  //删除掉选中的属性值
  attrParams.value.attrValueList.splice(index, 1);
};

//修改已有的平台属性与属性值
//row:代表已有的平台属性
const updateAttr = (row: attr) => {
  //切换场景为1
  scene.value = 1;
  //attrParams,发请求需要携带的参数
  //row:已有平台属性与属性值[属性值即为引用类型数据]
  //attrParams与row进行合并的时候,属性值数组是浅拷贝，指向统一地址,导致attrParams属性值的数据发生变化
  //row的属性值的数据页发生变化--->浅拷贝
  Object.assign(attrParams.value, cloneDeep(row));
};

//删除平台属性的方法
const removeAttr = async (id: number) => {
  //删除已有平台属性的请求
  try {
    //删除已有平台属性的请求
    await reqRemoveAttr(id);
    //顶部文字提示
    ElMessage({
      message: "删除成功",
      type: "success",
    });
    //获取删除以后剩余平台属性
    getAttrList();
  } catch (error) {
    ElMessage({
      message: "删除失败",
      type: "error",
    });
  }
};

//路由组件销毁的时候：清空仓库的数据
onUnmounted(() => {
  categoryStore.c1Id = "";
  categoryStore.c2Id = "";
  categoryStore.c3Id = "";
  categoryStore.c1Arr = [];
  categoryStore.c2Arr = [];
  categoryStore.c3Arr = [];
});
</script>

<style scoped>

</style>